import argparse
# from pathlib import Path
# import numpy as np
# import sys
# import json
# import yaml
# import random
# import pickle
from collections import defaultdict, OrderedDict

from utils.motion_util import parse_extrinsics


## this is for options
def config_parser():
    import configargparse
    parser = configargparse.ArgumentParser()
    '''
        parser.section(), parser.items()
    '''
    #### data config
    parser.add_argument('--exp_name', type=str, help='name used for save', default="debug")
    parser.add_argument('--num_view', type=int, help='using how many RGBD images to recon', default=4)
    parser.add_argument('--reso', type=str, help='h x w', default="480x640")
    parser.add_argument('--root_path', type=str, help='data path of imgs', default="/data/yangchen/ICL-NUIM/Di-Fusion_demo")
    parser.add_argument('--log_path', type=str, help='data path of logs', default='logs')
    parser.add_argument('--checkpoint_path', type=str, help='data path of model', default="ckpt")

    ### voxelization
    parser.add_argument('--depth_cut_min', type=float, default=0.5)
    parser.add_argument('--depth_cut_max', type=float, default=5.0)
    parser.add_argument('--voxel_size', type=float, default=0.1)
    parser.add_argument('--bound_min', type=float, nargs='+', default=[-3.5, -0.5, -2.5])
    parser.add_argument('--bound_max', type=float, nargs='+', default=[4.5, 3.5, 5.5])
    parser.add_argument('--prune_min_vox_obs', type=int, default=1)
    ### learning
    parser.add_argument('--lr', type=float, default=3e-4)
    parser.add_argument('--resume', action='store_true', help="whether resume")
    parser.add_argument('--load_path', type=str, help="the path for checkpoint",default=None)

    ### steps
    parser.add_argument('--num_epoch', type=int, default=10000)
    parser.add_argument('--num_valid', type=int, default=50)
    parser.add_argument('--num_print', type=int, default=10)
    parser.add_argument('--num_start', type=int, default=0)
    parser.add_argument('--num_save', type=int, default=1000)
    # parser.add_argument('--num_epoch', type=int, default=10000)

    #### ray matching
    parser.add_argument('-v', '--visualize', action='store_true', help='Visualize')

    parser.add_argument('--max_hits', type=int, default=10, help="the max hit iter of ray")
    parser.add_argument('--pixel_per_view', type=int, default=8192, help="sampling pixels of each view")
    parser.add_argument('--raymarching_stepsize_ratio', type=float, default=0.125, help="per voxel sample point")
    
    #### volume Render
    # ray-marching parameters
    parser.add_argument('--discrete-regularization', action='store_true',
                        help='if set, a zero mean unit variance gaussian will be added to encougrage discreteness')
    
    # additional arguments
    parser.add_argument('--chunk-size', type=int,
                        help='set chunks to go through the network (~K forward passes). trade time for memory.', default=128)
    parser.add_argument('--valid-chunk-size', type=int,
                        help='chunk size used when no training. In default the same as chunk-size.',default=256)
    parser.add_argument('--raymarching-tolerance', type=float, default=0)

    parser.add_argument('--trace-normal', action='store_true')
    
    
    ### use in network/loss
    parser.add_argument('--L1', action='store_true',
                        help='if enabled, use L1 instead of L2 for RGB loss')
    parser.add_argument('--color-weight', type=float, default=32.0)
    parser.add_argument('--depth-weight', type=float, default=32.0)
    parser.add_argument('--depth-weight-decay', type=str, default=None,
                        help="""if set, use tuple to set (final_ratio, steps).
                                For instance, (0, 30000)    
                            """)
    parser.add_argument('--alpha-weight', type=float, default=0.0)
    parser.add_argument('--vgg-weight', type=float, default=0.0)
    parser.add_argument('--eikonal-weight', type=float, default=0.0)
    parser.add_argument('--regz-weight', type=float, default=1.0)
    parser.add_argument('--vgg-level', type=int, choices=[1,2,3,4], default=2)
    parser.add_argument('--eval-lpips', action='store_true',
                        help="evaluate LPIPS scores in validation")
    parser.add_argument('--no-background-loss', action='store_true')

    return parser

def config_parser_extract_mesh():
    '''
        this func is used for extract mesh
        allocate all the parser
    '''
    parser = config_parser()
    
    parser.add_argument('--output', type=str, default="logs", help="save path")
    parser.add_argument('--name', type=str, default='sparsevoxel')
    parser.add_argument('--format', type=str, choices=['voxel_center', 'voxel_mesh', 'mc_mesh'])
    parser.add_argument('--savetext', action='store_true', help='save .ply in plain text')
    parser.add_argument('--mc-num-samples-per-halfvoxel', type=int, default=8,
                        help="""the number of point samples every half voxel-size for marching cube. 
                        For instance, by setting to 8, it will use (8 x 2) ^ 3 = 4096 points to compute density for each voxel.
                        In practise, the larger this number is, the more accurate surface you get.
                        """)
    parser.add_argument('--mc-threshold', type=float, default=0.5, 
                        help="""the threshold used to find the isosurface from the learned implicit field.
                        In our implementation, we define our values as ``1 - exp(-max(0, density))`` 
                        where "0" is empty and "1" is fully occupied.
                        """)
    # parser.add_argument('--user-dir', default='fairnr')
    parser.add_argument('--cpu', action='store_true')
    return parser